#include <QtGui>
#include <QtOpenGL>

#include <iostream>
#include <vector>
#include <cmath>

#include "../src/color.h"
#include "../src/vector3d.h"
#include "../src/mass.h"
#include "../src/spring.h"
#include "../src/mass_spring.h"
#include "../src/floor.h"
#include "../src/building.h"
#include "glwidget.h"

GLWidget::GLWidget(QWidget *parent) : QGLWidget(parent){
	system = NULL;
	
	t=0.0;
	
	timer = new QTimer(this);
	connect(timer, SIGNAL(timeout()), this, SLOT(calculate()));
	timer->start(100);
}

GLWidget::~GLWidget(){
	delete timer;
	delete system;
}

System* GLWidget::getSystem(){
	return system;
}

QSize GLWidget::minimumSizeHint() const{
	return QSize(150, 50);
}

QSize GLWidget::sizeHint() const{
	return QSize(700, 450);
}

void GLWidget::initializeGL(){
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glShadeModel(GL_FLAT);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
}

void GLWidget::paintGL(){
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	if (system != NULL) system->draw();
}

void GLWidget::calculate(){
	t = t + timer->interval()/100.0;
	if (system != NULL) system->calculate(t);
	updateGL();
}

void GLWidget::resizeGL(int _width, int _height){
	glViewport(0, 0, _width, _height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	if (_width<=_height)
		glFrustum(0.0, 2.0, 0.0*((double)_height)/_width, 2.0*((double)_height)/_width,     2.0, 1000.0);
	else
		glFrustum(0.0*((double)_width)/_height, 2.0*((double)_width)/_height,     -0.0, 2.0,     2.0, 1000.0);

	gluLookAt(0.0,0.0,11.0,  0.0,0.0,0.0,  0.0,1.0,0.0);
	glMatrixMode(GL_MODELVIEW);
}

void GLWidget::createMassSpring(int _n, double qrError){

//incluindo massas e molas

//numero de graus de liberdade
	int n = _n;
	double k = 1.0;
	double weigth = 10.0;

//para a criação igualmente espaçada
	double size = 10.0;
	double init = 1.0;

	std::vector<Mass> masses;
	std::vector<Spring> springs;

	for (int i = 0; i < n; i++){
		springs.push_back(Spring(Vector3D(init + (i * (size / n)),5.,0.), Vector3D(init + ((i + 1) * (size / n)),5.,0.), k, Color(1.0, 0.0, 0.0)));	//position begin, position end, k, color
		masses.push_back(Mass(weigth, Vector3D(init + ((i + 1) * (size / n)),5.,0.), Color(1.0, 1.0, 0.0)));	//weigth, position, d
		if (i == (n - 1)) springs.push_back(Spring(Vector3D(init + ((i + 1) * (size / n)),5.,0.), Vector3D(init + ((i + 2) * (size / n)),5.,0.), k, Color(1.0, 0.0, 0.0)));
	}
	std::cout << "criado massas e molas" << std::endl;

	if (this->system != NULL)
		delete this->system;
	
	this->system = new Mass_Spring(masses, springs);

	system->calculeVibrationMode(qrError);
}

void GLWidget::createBuilding(int _n, double qrError){
//numero de graus de liberdade
	int n = _n;
	//double k = 0.01;
	double width = 1.5;
	double height = width * 0.5;

	
	std::vector<Floor> floors;

	for (int i = 0; i < n; i++){
		floors.push_back(Floor(width, height, 3600.0/(i+1), Vector3D(6.0, i*height + 2.0, 0.0), Color((((double)n)/100.0) + 0.3, 0.08 * ((double)i), 0.8)));	//width, height, position
	}
	/*int i = 0;
	floors.push_back(Floor(width, height, 3600.0, Vector3D(6.0, i*height + 2.0, 0.0), Color((((double)n)/100.0) + 0.3, 0.08 * ((double)i), 0.8)));	//width, height, position
	i++;
	floors.push_back(Floor(width, height, 1800.0, Vector3D(6.0, i*height + 2.0, 0.0), Color((((double)n)/100.0) + 0.3, 0.08 * ((double)i), 0.8)));	//width, height, position
	i++;
	floors.push_back(Floor(width, height, 1200.0, Vector3D(6.0, i*height + 2.0, 0.0), Color((((double)n)/100.0) + 0.3, 0.08 * ((double)i), 0.8)));	//width, height, position
	i++;
	floors.push_back(Floor(width, height, 600.0, Vector3D(6.0, i*height + 2.0, 0.0), Color((((double)n)/100.0) + 0.3, 0.08 * ((double)i), 0.8)));	//width, height, position
	std::cout << "criado andares" << std::endl;
*/
	if (this->system != NULL)
		delete this->system;
	
	this->system = new Building(floors);

	system->calculeVibrationMode(qrError);
}
